package com.rrd.hive.udf;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import org.apache.hadoop.hive.common.type.HiveDecimal;
import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.exec.UDFArgumentTypeException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDF;
import org.apache.hadoop.hive.serde2.io.HiveDecimalWritable;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.DoubleObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.StringObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.WritableHiveDecimalObjectInspector;
public class AmortizeAmtUDF extends GenericUDF{
	private WritableHiveDecimalObjectInspector decimalOI;
	private WritableHiveDecimalObjectInspector decimalOI2;
	private WritableHiveDecimalObjectInspector decimalOI3;
	
	private StringObjectInspector stringOI;
	
	@Override
	public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException {
		// TODO Auto-generated method stub
		if(arguments==null || arguments.length!=4){
			 throw new UDFArgumentTypeException(arguments.length, "输入参数不正确!");
		}
		ObjectInspector loankey=arguments[0];
		ObjectInspector loanAmt=arguments[1];
		ObjectInspector loanRate=arguments[2];
		ObjectInspector dueAmt=arguments[3];
		System.out.println(arguments[1]);
		if(! (loankey instanceof StringObjectInspector)){
			throw new UDFArgumentException("第一个参数进件KEY必须为字符型");
		}
		if(!(loanAmt instanceof  DoubleObjectInspector) && !(loanAmt instanceof  WritableHiveDecimalObjectInspector) ){
			throw new UDFArgumentException("第二个参数借款金额必须为数字型"+(loanAmt.getClass()));
		}
		if(!(loanAmt instanceof  DoubleObjectInspector) && !(loanRate instanceof  WritableHiveDecimalObjectInspector) ){
			throw new UDFArgumentException("第三个参数利率必须为数字型");
		}
		if(!(dueAmt instanceof  DoubleObjectInspector) && !(loanAmt instanceof  WritableHiveDecimalObjectInspector)){
			throw new UDFArgumentException("第四个参数应还款额必须为数字类型");
		}
		this.stringOI =(StringObjectInspector) loankey;
		this.decimalOI = (WritableHiveDecimalObjectInspector) loanAmt;
		this.decimalOI2 = (WritableHiveDecimalObjectInspector) loanRate;
		this.decimalOI3 = (WritableHiveDecimalObjectInspector) dueAmt;
		
		return ObjectInspectorFactory.getStandardListObjectInspector(
                PrimitiveObjectInspectorFactory.writableHiveDecimalObjectInspector);
	}
	private List<HiveDecimalWritable> list = new ArrayList();
	private String pre_loan_key=null;
	private BigDecimal pre_cost_amt=null;
	private BigDecimal az_interest_amt=null; //摊销利息
	private BigDecimal az_princal_amt=null; //摊销本金
	private BigDecimal az_cost_amt=null; //摊余成本
	@Override
	public Object evaluate(DeferredObject[] arguments) throws HiveException {
		// TODO Auto-generated method stub
		list.clear();
		String loan_key = this.stringOI.getPrimitiveJavaObject(arguments[0].get());
		BigDecimal loan_amt=this.decimalOI.getPrimitiveJavaObject(arguments[1].get()).bigDecimalValue();
		BigDecimal loan_rate=this.decimalOI2.getPrimitiveJavaObject(arguments[2].get()).bigDecimalValue();
		BigDecimal due_amt=this.decimalOI3.getPrimitiveJavaObject(arguments[3].get()).bigDecimalValue();
		
		if(this.pre_loan_key==null || !this.pre_loan_key.equals(loan_key)){
			//计算第一期
			pre_cost_amt = loan_amt;
			pre_loan_key=loan_key;
			this.az_interest_amt = pre_cost_amt.multiply(loan_rate);
			this.az_princal_amt= due_amt.subtract(this.az_interest_amt);
			this.az_cost_amt = pre_cost_amt.subtract(this.az_princal_amt);
			this.pre_cost_amt=this.az_cost_amt;
			
		}
		else {
			this.az_interest_amt = pre_cost_amt.multiply(loan_rate);
			this.az_princal_amt= due_amt.subtract(this.az_interest_amt);
			this.az_cost_amt = pre_cost_amt.subtract(this.az_princal_amt);
			this.pre_cost_amt=this.az_cost_amt;
			pre_loan_key=loan_key;
		}
		HiveDecimalWritable hdm = new HiveDecimalWritable();
		hdm.set(HiveDecimal.create(this.az_interest_amt));
//		hdm.set(HiveDecimal.create(pre_cost_amt.multiply(loan_rate)));
		list.add(0, hdm);
//		list.add(1, new HiveDecimalWritable(HiveDecimal.create(pre_cost_amt)));
//		list.add(2, new HiveDecimalWritable(HiveDecimal.create(loan_rate)));
		list.add(1, new HiveDecimalWritable(HiveDecimal.create(this.az_princal_amt)));
		list.add(2, new HiveDecimalWritable(HiveDecimal.create(this.az_cost_amt)));
		return list;
	}

	@Override
	public String getDisplayString(String[] children) {
		// TODO Auto-generated method stub
		return null;
	}

	public static void main(String[] args) {
		BigDecimal loan_amt = BigDecimal.valueOf(2500);
		BigDecimal pre_cost_amt=loan_amt;
		BigDecimal rate = BigDecimal.valueOf(0.04817325348);
		System.out.println(loan_amt.multiply(rate));
		System.out.println(pre_cost_amt.multiply(rate));
		System.out.println(pre_cost_amt.subtract(BigDecimal.valueOf(500)));
		System.out.println(pre_cost_amt);
	}
}
